from pymongo import MongoClient, errors
import gridfs
import os
from API import config

Host = config['mongodb']['host']
Port = config['mongodb']['port']
DBname = config['mongodb']['db_name']
CollectionName = config['mongodb']['collection_name']


def get_connection(host=Host, port=Port, dbname=DBname, collectionName=CollectionName):
    client = MongoClient(host, port)
    db = client[dbname]
    collection = db[collectionName]
    return client, db, collection


def check_connection():
    print "Checking MongoDB Connection......"
    print "Host: ", Host, "Port: ", Port
    client = MongoClient(Host, Port)
    print "Getting Client......Success!"
    print "Database Name: ", DBname
    db = client[DBname]
    print "Getting Database......Success!"
    lst = db.collection_names()
    print "Collection Name: ", lst
    try:
        client.admin.command('enableSharding', DBname)
        client.admin.command('shardcollection', 'test.FST', key={'_id': 'hashed'})
        client.admin.command('shardcollection', 'test.chunks', key={'files_id': 'hashed'})
        client.admin.command('shardcollection', 'test.files', key={'_id': 'hashed'})
    except errors.OperationFailure:
        pass


KEY = {'set_id': "",
       'user_id': "",
       'name': '',
       'type': '',
       'desc': '',
       'size': '',
       'abs_path': '',
       'all_dir': ''
       }


class Fst:
    # KEY={'M_Uname':'','M_Upwd':'','M_Upriv':''}
    def __init__(self, **kwargs):
        tmp_key = KEY.copy()
        for each in tmp_key.keys():
            tmp_key[each] = kwargs[each]
        tmp_key.update(kwargs['all_dir'])
        self.__dict__.update(tmp_key)

    def save(self):
        client, db, collection = get_connection()

        re = collection.find_one({"abs_path": self.abs_path})
        if re:
            raise KeyError(self.name + ': Filename already exist!')

        fs = gridfs.GridFS(db)
        fd = open(self.abs_path, 'r')
        fid = fs.put(fd, filename=self.abs_path)
        fd.close()
        self.GFS_id = fid
        tmp_key = self.__dict__.copy()
        tmp_key['GFS_id'] = fid
        collection.insert_one(tmp_key)
        self.id = tmp_key['_id']
        client.close()

    def delete(self):
        client, db, collection = get_connection()
        re = collection.find_one({'GFS_id': self.GFS_id, 'name': self.name
                                  })
        if re:
            oId = re['_id']
            fs = gridfs.GridFS(db)
            fs.delete(self.GFS_id)
            collection.delete_one({'_id': oId})
            client.close()
        else:
            raise KeyError("No instance in db!")

    @staticmethod
    def get(id):
        client, db, collection = get_connection()
        re = collection.find_one({'_id': id})
        oid = re['_id']
        gird_fs = re['GFS_id']
        re.pop('_id')
        re.pop('GFS_id')
        tmp = Fst(**re)
        tmp.id = oid
        tmp.GFS_id = gird_fs
        return tmp

    @staticmethod
    def filter(**kwargs):
        for each in kwargs.keys():
            if each not in KEY:
                raise KeyError(each + ": Key Error!")
        client, db, collection = get_connection()
        re = collection.find(kwargs)
        lst = []
        for each in re:
            tmp = Fst.get(each['_id'])
            lst.append(tmp)
        return lst

    def update(self, **kwargs):
        for each in kwargs.keys():
            if each not in KEY:
                raise KeyError(each + ' : Key Errror!')
        client, db, collection = get_connection()
        collection.update_one({'_id': self.id}, {'$set': kwargs})
        self.__dict__.update(kwargs)
        # collection.update_one({'_id':self.id},{'$set':kwargs},bypass_document_validation=True)
        client.close()

    def download(self):
        client, db, collection = get_connection()
        fs = gridfs.GridFS(db)
        gf = fs.get(self.GFS_id)
        file = gf.read()
        try:
            output = open(self.abs_path, 'wb')
        except:
            os.makedirs(os.path.dirname(self.abs_path))
            output = open(self.abs_path, 'wb')
        output.write(file)
        output.close()
        gf.close()
        client.close()


if __name__ == '__main__':
    os.chdir('D:\plat\py-server')
    check_connection()
